﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;

namespace MefContainer
{
    public static class MefHelper
    {
        #region 字段
        private static CompositionContainer _container;
        private static List<Assembly> _assemblies;
        /// <summary>
        /// 排除字符串
        /// </summary>
        private static List<string> _exceptString;
        #endregion

        #region 属性
        public static List<Assembly> Assemblies
        {
            get
            {
                return _assemblies;
            }
        }
        #endregion

        #region 公有方法

        /// <summary>
        /// 扫描目录下所有程序集
        /// </summary>
        public static void Init(List<string> exceptString = null)
        {
            _assemblies = new List<Assembly>();
            _exceptString = exceptString ?? new List<string>();

            LoadAssembly();

            var catalog = new AggregateCatalog();

            _assemblies.ForEach(x =>
            {
                catalog.Catalogs.Add(new AssemblyCatalog(x));
            });

            _container = new CompositionContainer(catalog);
        }

        public static T GetExportedValue<T>()
        {
            return _container.GetExportedValue<T>();
        }

        public static T GetExportedValue<T>(string contract)
        {
            return _container.GetExportedValue<T>(contract);
        }

        public static T GetExportedValue<T>(Type service)
        {
            return _container.GetExportedValue<T>(AttributedModelServices.GetContractName(service));
        }

        public static T GetExportedValue<T>(Type service, string key)
        {
            var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;

            return _container.GetExportedValue<T>(contract);
        }

        public static IEnumerable<T> GetExportedValues<T>()
        {
            return _container.GetExportedValues<T>();
        }

        public static IEnumerable<T> GetExportedValues<T>(string contract)
        {
            return _container.GetExportedValues<T>(contract);
        }

        public static IEnumerable<T> GetExportedValues<T>(Type service, string key)
        {
            var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;

            return _container.GetExportedValues<T>(contract);
        }

        public static void SatisfyImportsOnce(object instance)
        {
            _container.SatisfyImportsOnce(instance);
        }

        public static void Compose(CompositionBatch batch)
        {
            _container.Compose(batch);
        }
        #endregion

        #region 私有方法
        private static void LoadAssembly()
        {
            var path = AppDomain.CurrentDomain.BaseDirectory;

            DirectoryInfo directory = new DirectoryInfo(path);

            var exeFiles = directory.GetFiles("*.exe", SearchOption.AllDirectories).ToList();
            var dllFiles = directory.GetFiles("*.dll", SearchOption.AllDirectories).ToList();

            exeFiles.AddRange(dllFiles);

            if (_exceptString.Any())
            {
                _exceptString.ForEach(exceptStr =>
                {
                    exeFiles.Where(x => x.Name.StartsWith(exceptStr)).ToList().ForEach(x => { exeFiles.Remove(x); });
                });
            }

            foreach (var file in exeFiles)
            {
                var x = Assembly.LoadFile(file.FullName);
                _assemblies.Add(x);
            }
        }
        #endregion


    }
}